import neopixel
from machine import Pin
import time
import asyncio


def wheel(pos):
    # 彩虹色生成器
    if pos < 85:
        return (pos * 3, 255 - pos * 3, 0)
    elif pos < 170:
        pos -= 85
        return (255 - pos * 3, 0, pos * 3)
    else:
        pos -= 170
        return (0, pos * 3, 255 - pos * 3)


"""
WS2812 WS2812B 灯带
"""


class WS2812:
    def __init__(self, pin, n=10):
        self.__brightness = 100
        self.__pin = Pin(pin, Pin.OUT)
        self.set_num(n)
        self.__loop = False
        self.__mode = 'rainbow'
        self.__task = None

    def set_num(self, n):
        self.__np = neopixel.NeoPixel(self.__pin, n)

    def start(self, mode):
        self.__loop = True
        self.__mode = mode
        if self.__task is None:
            self.__task = asyncio.create_task(self.__loop_task())

    def stop(self):
        self.__loop = False

    async def __loop_task(self):
        while self.__loop:
            if self.__mode == "rainbow":
                await self.rainbow()
            elif self.__mode == "rolling":
                await self.rolling()
            await asyncio.sleep_ms(10)
        self.__task = None

    async def rainbow(self, wait=20):
        j = 0
        while self.__loop and self.__mode == "rainbow":
            n = self.__np.n
            for i in range(n):
                idx = (i * 256 // n + j) & 255
                color = wheel(idx)
                self.__np[i] = tuple(int(c * self.__brightness / 100) for c in color)
            self.__np.write()
            await asyncio.sleep_ms(wait)
            j = (j + 1) % 256

    async def rolling(self, pattern=None, wait=100):
        if pattern is None:
            pattern = [
                (255, 0, 0),
                (0, 255, 0),
                (0, 0, 255),
            ]

        pattern_len = len(pattern)
        j = 0
        while self.__loop and self.__mode == "rolling":
            n = self.__np.n
            for i in range(n):
                color = pattern[(i + j) % pattern_len]
                self.__np[i] = tuple(int(c * self.__brightness / 100) for c in color)
            self.__np.write()
            await asyncio.sleep_ms(wait)
            j = (j + 1) % pattern_len

    def setBrightness(self, brightness):
        self.__brightness = brightness

    def fill(self, color):
        n = self.__np.n
        v = (int(color[0] * self.__brightness / 100), int(color[1] * self.__brightness / 100),
             int(color[2] * self.__brightness / 100))
        for i in range(n):
            self.__np[i] = v
        self.__np.write()

    def fade_in_out(self, count=1):
        n = self.__np.n
        for i in range(0, count * 2 * 256, 8):
            for j in range(n):
                if (i // 256) % 2 == 0:
                    val = i & 0xFF
                else:
                    val = 255 - (i & 0xFF)
                self.__np[j] = (val, val, val)
            self.__np.write()

    def cycle(self):
        n = self.__np.n
        for i in range(4 * n):
            for j in range(n):
                self.__np[j] = (0, 0, 0)
            self.__np[i % n] = (255, 255, 255)
            self.__np.write()
            time.sleep_ms(25)

    def bounce(self):
        n = self.__np.n
        for i in range(4 * n):
            for j in range(n):
                self.__np[j] = (0, 0, 128)
            if (i // n) % 2 == 0:
                self.__np[i % n] = (0, 0, 0)
            else:
                self.__np[n - 1 - (i % n)] = (0, 0, 0)
            self.__np.write()
            time.sleep_ms(60)

    def clear(self):
        for i in range(self.__np.n):
            self.__np[i] = (0, 0, 0)
        self.__np.write()


if __name__ == "__main__":
    ws2812_led = WS2812(1, 10)
    ws2812_led.clear()
    ws2812_led.fade_in_out()


    async def async_loop():
        ws2812_led.start("rolling")  # ✅ 启动动画
        await asyncio.sleep(5)  # 播放 5 秒
        ws2812_led.set_num(60)
        await asyncio.sleep(5)
        ws2812_led.stop()  # ✅ 停止动画

    asyncio.run(async_loop())

